/*
 * Copyright (c) 2023 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#ifndef _INTERFACE_BLOCKIO_H_
#define _INTERFACE_BLOCKIO_H_

#include "chip/bus_lock.h"
#include "internal/bus/bus_base/bus.h"
#include "internal/chip/chip_base/chip.h"
#include <device_tree/interface/Chip/BlockIO.h>
#include <map>
#include <mc/core/timer.h>
#include <mc/engine/service.h>
#include <mc/exception.h>
#include <memory>
#include <string>
#include <variant>
#include <vector>

namespace dev {

// 序列化相关常量定义 - 与skynet原版完全兼容
namespace seri_constants {
constexpr int MAX_COOKIE        = 32; // 最大cookie值
constexpr int TYPE_NIL          = 0;  // null类型
constexpr int TYPE_BOOLEAN      = 1;  // 布尔类型
constexpr int TYPE_NUMBER       = 2;  // 数字类型
constexpr int TYPE_SHORT_STRING = 4;  // 短字符串类型
constexpr int TYPE_LONG_STRING  = 5;  // 长字符串类型
constexpr int TYPE_TABLE        = 6;  // 表类型
// 注意：移除了TYPE_BINARY，因为原版skynet不支持
} // namespace seri_constants

/**
 * 序列化支持的数据类型
 * 参考 lua-seri 实现，支持多种基本数据类型
 * 使用 std::variant 确保类型安全
 * 注意：二进制数据将被转换为字符串格式以保持skynet兼容性
 */
using seri_value = std::variant<std::nullptr_t,      // null值
                                bool,                // 布尔值
                                int8_t,              // 8位有符号整数
                                uint8_t,             // 8位无符号整数
                                int16_t,             // 16位有符号整数
                                uint16_t,            // 16位无符号整数
                                int32_t,             // 32位有符号整数
                                uint32_t,            // 32位无符号整数
                                int64_t,             // 64位有符号整数
                                uint64_t,            // 64位无符号整数
                                float,               // 单精度浮点数
                                double,              // 双精度浮点数
                                std::string,         // 字符串
                                std::vector<uint8_t> // 二进制数据（将转换为字符串序列化）
                                >;

/**
 * BlockIO 接口类
 *
 * 提供块设备I/O操作和序列化功能
 * 序列化功能参考 lua-seri 实现，与skynet原版完全兼容
 *
 * 序列化格式特点：
 * - 紧凑的二进制格式
 * - 支持多种数据类型
 * - 类型安全
 * - 高效的流式处理
 * - 与skynet.unpack完全兼容
 */
class Interface_BlockIO : public mc::engine::interface<Interface_BlockIO, gen::BlockIO> {
public:
    Interface_BlockIO()  = default;
    ~Interface_BlockIO() = default;

    std::vector<uint8_t> PluginRequest(std::map<std::string, std::string> context,
                                       const std::string&                 plugin_name,
                                       const std::string&                 plugin_cmd,
                                       const std::vector<uint8_t>&        params) override;

    /**
     * 序列化方法：将数据打包成二进制格式
     * 参考 lua-seri 的 luaseri_pack 实现，与skynet完全兼容
     *
     * @param data 要序列化的数据向量
     * @return 序列化后的二进制数据
     *
     * 支持的数据类型包括：null、布尔值、各种整数类型、浮点数、字符串
     * 序列化格式采用紧凑的二进制格式，每个值包含类型字节和数据部分
     * 二进制数据将被转换为字符串格式以保持兼容性
     */
    std::vector<uint8_t> seri_pack(const std::vector<seri_value>& data);

    /**
     * 反序列化方法：将二进制数据解包成原始数据
     * 参考 lua-seri 的 luaseri_unpack 实现，与skynet完全兼容
     *
     * @param packed_data 要反序列化的二进制数据
     * @return 反序列化后的数据向量
     *
     * 如果数据format无效或损坏，会抛出 mc::invalid_op_exception 异常
     * 支持流式解析，可以处理大量数据
     * 完全兼容skynet.pack生成的数据
     */
    std::vector<seri_value> seri_unpack(const std::vector<uint8_t>& packed_data);

    chip_base* m_chip = nullptr;
};

} // namespace dev

#endif // _INTERFACE_BLOCKIO_H_
